package sku

import (
	"context"
	"fmt"
	tools "mall/common/utils"
	"mall/services/product/rpc/internal/domain/bo"
	"mall/services/product/rpc/internal/domain/do"
	"mall/services/product/rpc/internal/mapper"
	"mall/services/product/rpc/internal/mapper/entity"
	"strings"

	"mall/services/product/rpc/internal/svc"
	"mall/services/product/rpc/pb"

	"github.com/zeromicro/go-zero/core/logx"
)

type ListLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewSkuListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListLogic {
	return &ListLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *ListLogic) SkuList(in *pb.SkuListDTO) (*pb.SkuListVO, error) {
	// 1.select count
	skuMapper, returnPbVO, selectCountErr := selectCount(in, l)
	if selectCountErr != nil {
		return nil, selectCountErr
	}
	// 1.1 if select count == 0
	if returnPbVO != nil {
		return returnPbVO, nil
	}
	// 2.select sku list
	skuInfoDOArr, err := skuMapper.SelectSkuListBySpuId(l.ctx, l.svcCtx.DBEngin, in.SpuId)
	if err != nil {
		return nil, err
	}
	// 3.select sku Attr
	querySkuAttrMap, err := l.querySkuAttr(in)
	if err != nil {
		return nil, err
	}
	// 4.packageObj
	skuList := l.packageObj(in, skuInfoDOArr, querySkuAttrMap)
	// 5.returnObj
	return &pb.SkuListVO{Records: skuList}, nil
}

func selectCount(in *pb.SkuListDTO, l *ListLogic) (*mapper.SkuMapper, *pb.SkuListVO, error) {
	skuMapper := mapper.NewSkuMapper()
	skuBO := bo.SkuBO{}
	skuBO.SpuId = in.SpuId
	skuBO.SkuNameAllLike = in.Name
	skuBO.Status = int64(in.Status)
	selectCountCtx, err := skuMapper.SelectCountCtx(l.ctx, l.svcCtx.DBEngin, skuBO)
	if err != nil {
		return nil, nil, err
	}
	if selectCountCtx <= 0 {
		return nil, &pb.SkuListVO{}, nil
	}
	return skuMapper, nil, nil
}

func (l *ListLogic) packageObj(in *pb.SkuListDTO, skuInfoDOArr []do.SkuInfoDO,
	querySkuAttrMap map[int64][]entity.SpuSkuAttrValueEntity) []*pb.SkuInfoVO {

	var skuList []*pb.SkuInfoVO
	for _, v := range skuInfoDOArr {
		// filter condition  SkuName
		if len(strings.TrimSpace(in.GetName())) > 0 {
			if !strings.Contains(v.SkuName, in.Name) {
				continue
			}
		}
		// filter condition status
		if in.Status != 0 && int32(v.Status) != in.Status {
			continue
		}
		vo := new(pb.SkuInfoVO)
		vo.SkuId = v.SkuId
		vo.SkuName = v.SkuName
		vo.Attrs = v.Attrs
		vo.ImgUrl = v.ImgUrl
		vo.PriceFee = v.PriceFee
		vo.MarketPriceFee = v.MarketPriceFee
		vo.PartyCode = v.PartyCode
		vo.ModelId = v.ModelId
		vo.Weight = float32(v.Weight)
		vo.Volume = float32(v.Volume)
		vo.Stock = int32(v.ActualStock)
		vo.TotalStock = int32(v.Stock)
		vo.Status = int32(v.Status)
		spuSkuAttrValueArr := querySkuAttrMap[v.SkuId]
		var spuSkuAttrArr []*pb.SpuSkuAttrValueVO
		if len(spuSkuAttrValueArr) > 0 {
			for _, v := range spuSkuAttrValueArr {
				skuAttr := new(pb.SpuSkuAttrValueVO)
				skuAttr.SpuSkuAttrValueId = v.SpuSkuAttrId
				skuAttr.AttrId = v.AttrId
				skuAttr.AttrName = v.AttrName
				skuAttr.AttrValueId = v.AttrValueId
				skuAttr.AttrValueName = v.AttrValueName
				spuSkuAttrArr = append(spuSkuAttrArr, skuAttr)
			}
		}
		vo.SpuSkuAttrValues = spuSkuAttrArr
		skuList = append(skuList, vo)
	}
	return skuList
}

func (l *ListLogic) querySkuAttr(in *pb.SkuListDTO) (map[int64][]entity.SpuSkuAttrValueEntity, error) {
	attrValueMapper := mapper.NewSpuSkuAttrValueMapper()
	spuSkuAttrValueBO := bo.SpuSkuAttrValueBO{SpuId: in.SpuId}
	skuAttrArr, err := attrValueMapper.SelectListCtx(l.ctx, l.svcCtx.DBEngin, spuSkuAttrValueBO)
	if err != nil {
		return nil, err
	}
	spuSkuAttrValueMap := make(map[int64][]entity.SpuSkuAttrValueEntity)
	for _, v := range skuAttrArr {
		skuAttrValueBOList := spuSkuAttrValueMap[v.SkuId]
		if skuAttrValueBOList == nil {
			skuAttrValueBOList = make([]entity.SpuSkuAttrValueEntity, 0)
		}
		skuAttrValueBOList = append(skuAttrValueBOList, v)
		spuSkuAttrValueMap[v.SkuId] = skuAttrValueBOList
	}
	fmt.Println(tools.BeanToJson(spuSkuAttrValueMap))
	return spuSkuAttrValueMap, nil
}
